package main

import (
	"flag"
	"fmt"
	"local-image-browser/common"
	"local-image-browser/lib/yml"
	"log"
	"net/http"
	"os"
	"path"
	"path/filepath"

	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/binding"
)

type ConfigPath struct {
	Name string
	Path string
}

type PathListResp struct {
	Name   string `json:"name"`
	Path   string `json:"path"`
	PathId string `json:"pathId"`
}

type Config struct {
	Name  string
	Port  string
	Paths map[string]ConfigPath
}

type FileInfo struct {
	Name string `json:"name"`
	Path string `json:"path"`
	Url  string `json:"url"`
}

var config = Config{}

func WriteConfFile() error {
	ymlName := "./local-image-browser.yml"
	config := Config{}
	config.Name = "Local-Image-Browser"
	config.Port = "8081"
	config.Paths = map[string]ConfigPath{
		"default": {

			Name: "默认目录",
			Path: "./",
		},
	}

	return yml.WriteConfig(ymlName, config)
}

func FileExists(filename string) bool {
	_, err := os.Stat(filename)
	return !os.IsNotExist(err)
}

// func listFiles(directory string) ([]string, error) {
// 	var files []string

// 	// 使用Walk函数遍历目录下的所有文件和子目录
// 	err := filepath.Walk(directory, func(path string, info os.FileInfo, err error) error {
// 		if err != nil {
// 			return err
// 		}

// 		// 如果是文件而不是目录，将文件路径添加到切片中
// 		if !info.IsDir() {
// 			files = append(files, path)
// 		}

// 		return nil
// 	})

// 	return files, err
// }

func listFiles(directory string, pathId string) ([]FileInfo, error) {
	var files []FileInfo

	// 使用ReadDir函数读取目录下的文件和子目录信息
	fileInfos, err := os.ReadDir(directory)
	if err != nil {
		return files, err
	}

	// 遍历目录下的文件和子目录
	for _, fileInfo := range fileInfos {
		// 如果是文件而不是目录，将文件路径添加到切片中
		ext := path.Ext(fileInfo.Name())
		if !fileInfo.IsDir() && ext == ".svg" {
			files = append(files, FileInfo{
				Name: fileInfo.Name(),
				Path: filepath.Join(directory, fileInfo.Name()),
				Url:  "/getFile/" + pathId + "/" + fileInfo.Name(),
			})
		}
	}

	return files, nil
}

func getPathByPathId(pathId string) (string, bool) {
	if v, ok := config.Paths[pathId]; ok {
		return v.Path, true
	} else {
		return "", false
	}
}

func getPathList(c *gin.Context) {
	resp := []PathListResp{}
	for k, v := range config.Paths {
		resp = append(resp, PathListResp{
			PathId: k,
			Name:   v.Name,
			Path:   v.Path,
		})
	}
	common.ApiReturnSuccess(c, gin.H{
		"pathList": resp,
	})
}

func getSvgList(c *gin.Context) {
	type Req struct {
		PathId string `json:"pathId"`
	}

	req := Req{}
	if err := c.ShouldBindBodyWith(&req, binding.JSON); err != nil {
		common.ApiReturnError(c, "param error:"+err.Error())
		return
	}

	var path = ""

	if v, ok := getPathByPathId(req.PathId); !ok {
		common.ApiReturnError(c, "pathId not exist")
		return
	} else {
		path = v
	}

	paths, err := listFiles(path, req.PathId)
	if err != nil {
		common.ApiReturnError(c, "file error"+err.Error())
		return
	}
	if len(paths) == 0 {
		common.ApiReturnError(c, "not file")
	} else {
		common.ApiReturnSuccess(c, gin.H{
			"fileList": paths,
		})
	}

}

func getFile(c *gin.Context) {
	pathId := c.Param("pathId")
	fileName := c.Param("fileName")
	_DS_ := string(filepath.Separator)

	if path, ok := getPathByPathId(pathId); ok && fileExists(path+_DS_+fileName) {
		fileFull := path + _DS_ + fileName
		fileContent, err := os.ReadFile(fileFull)
		// 设置Content-Disposition头，让浏览器直接显示而不是下载
		c.Header("Content-Disposition", "inline")
		if err != nil {
			c.String(http.StatusInternalServerError, "Error reading file")
			return
		}
		c.Data(http.StatusOK, "image/svg+xml", fileContent)
	} else {
		c.String(http.StatusNotFound, "")
	}

}

func fileExists(filePath string) bool {
	_, err := os.Stat(filePath)
	return !os.IsNotExist(err)
}

func StartServer(port string) {
	router := gin.Default()

	// 定义一个GET请求的路由
	router.POST("/api/getSvgList", getSvgList)
	router.POST("/api/getPathList", getPathList)
	router.Any("/getFile/:pathId/:fileName", getFile)

	// 启动HTTP服务器
	router.Run(":" + port)
}

func main() {
	var defaultConfYmlPath = "./local-image-browser.yml"
	var cfgPath string
	var ec bool
	flag.StringVar(&cfgPath, "c", defaultConfYmlPath, "config file path")
	flag.BoolVar(&ec, "ec", false, "generate sample configuration file")
	flag.Parse()

	if ec {
		if err := WriteConfFile(); err != nil {
			log.Fatalln("ERROR:", err)
		}
		return
	}

	if err := yml.ReadConfig(defaultConfYmlPath, &config); err != nil {
		log.Fatalln("ERROR:", err)
		return
	}

	fmt.Println("opoooo", config)
	StartServer(config.Port)
}
